const {DataUtils} = require("./data_utils");

const {bcostars} = require("../tars/TransactionTars");



const {ECDSAUtils} = require("../utils/ecdsa_util");
class TxUtils {
    //helper 方法，传入hex字符串（abi编码),解码为二进制，设置txdata的input字段,目标类型为binBuffer
    static set_txdata_input(txdata,inputs_hex){
        //console.log("set_txdata_input",txdata,inputs_hex);
        var bindata = DataUtils.hexToArray(inputs_hex);
        txdata.input.readFromObject(Buffer.from(bindata));
    }
    /*将TransactionData 按自定义的方式序列化成二进制数组*/
    static build_txdata_stream(tx) {
        /*
        BCOSCPP SDK里按以下顺序和字节格式对TransactionData进行字节层面的连接，并算hash
        这样做（而不是采用tars stream)的方式，是考虑到效率，直接用hash实现的update方法，无需先序列化，再调hash，而产生了多余的内存拷贝
        (int32_t)version
        chainID.data()
        groupID.data()
        (int64_t)blockLimit
        nonce.data()
        to.data()
        input.data()
        abi.data()
         */
        var streambuffer = []
        var buffer = DataUtils.int32ToBytes(tx.version);
        streambuffer.push(...buffer)
        streambuffer.push(...DataUtils.strToBytes(tx.chainID))
        streambuffer.push(...DataUtils.strToBytes(tx.groupID))
        var buffer = DataUtils.int64ToBytes(tx.blockLimit);
        streambuffer.push(...buffer)
        streambuffer.push(...DataUtils.strToBytes(tx.nonce))
        streambuffer.push(...DataUtils.strToBytes(tx.to))
        var buffer = DataUtils.bufferToBytes(tx.input)
        streambuffer.push(...buffer)
        streambuffer.push(...DataUtils.strToBytes(tx.abi))
        return streambuffer
    }


    /**
     * 传入TransactionData, TxHash, 签名串，构建Transaction,
     * 即可以发给节点的、签过名的rawTransaction,二进制格式
     * bcos cpp sdk里的实现，就是tars直接序列化流了
     * tars::TarsOutputStream<tars::BufferWriter> output;
     *     _transaction.writeTo(output);
     */
    /*填充tx的字段值*/
    static set_transaction(txdata,txhash,signresult){
        var tx = new bcostars.Transaction();
        tx.attribute = 0;
        tx.importTime = 0;
        tx.data = txdata;
        tx.dataHash.readFromObject(Buffer.from(txhash));
        tx.signature.readFromObject(Buffer.from(signresult));
        tx.extraData = "";
        return tx;
    }

    /*序列化输出tx*/
    static build_rawtransaction_stream(txdata, txhash, signresult) {
        var tx = this.set_transaction(txdata,txhash,signresult);
        var buffer = tx.toBinBuffer();
        //console.log(buffer);
        return DataUtils.bufferToBytes(buffer);
    }

    //创建raw transaction data,含签名流程，返回二进制结果
    static build_rawtransaction_by_txdata(txdata, privkey){
        const txdatastream = this.build_txdata_stream(txdata);
        const txhash = ECDSAUtils.calc_hash(txdatastream);
        //const txhash_bytes = ethers.getBytes("0x"+txhash);
        const txhash_bytes = DataUtils.hexToArray(txhash);
        const sigresult = ECDSAUtils.sign(txhash_bytes,privkey);
        //console.log("sigresult:",sigresult);

        const rawtxdata = this.build_rawtransaction_stream(txdata,txhash_bytes,DataUtils.hexToArray(sigresult));
        return rawtxdata;
        //const rawtxdata_hex = ethers.hexlify(rawtxdata)
        //return rawtxdata_hex;
    }
}

module.exports.TxUtils = TxUtils;